package com.uziot.activiti6.controller;

import com.uziot.activiti6.common.dto.HistoricTaskInstanceDTO;
import com.uziot.activiti6.common.dto.TaskDTO;
import com.uziot.activiti6.common.util.Result;
import com.uziot.activiti6.controller.vo.*;
import com.uziot.activiti6.service.ActivitiService;
import com.uziot.activiti6.service.ProcessImageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.StreamUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author shidt
 * @version V1.0
 * @className FlowTaskProvider
 * @date 2021-02-26 10:38:41
 * @description 任务相关
 */

@RestController
@Slf4j
@Api(tags = "流程-任务控制类接口")
@RequestMapping(value = {"/api/flowTask"})
public class FlowTaskController {

    @Autowired
    private ActivitiService activitiService;
    @Autowired
    private ProcessImageService processImageService;

    /***
     * 开始流程
     */
    @PostMapping(value = "/startTask")
    @ApiOperation(value = "开始流程", notes = "开始流程")
    public Result startProcessInstance(@RequestBody @Validated @ApiParam(value = "开始流程请求对象")
                                       @Valid StartProcessInstanceRequest startProcessInstanceRequest) {
        try {
            // 流程配置参数
            String applyUserId = startProcessInstanceRequest.getApplyUserId();
            // 流程实例Key
            String instanceKey = startProcessInstanceRequest.getInstanceKey();
            // 流程发起人
            Map<String, Object> variables = startProcessInstanceRequest.getVariables();
            variables.put("applyUserId", applyUserId);
            // 发起流程
            ProcessInstance processInstance = activitiService.startProcessInstance(instanceKey, variables);
            log.debug("processInstance:" + processInstance.getProcessDefinitionId());
            return Result.ok().put("processInstanceId", processInstance.getId());
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }

    /***
     * 查询待办任务
     * @param queryWaitTaskRequest queryWaitTaskRequest
     * @return Result
     */

    @PostMapping(value = "/queryWaitTask")
    @ApiOperation(value = "查询待办任务", notes = "查询待办任务")
    public Result queryWaitTask(@RequestBody @ApiParam(value = "查询任务请求对象") @Valid
                                        QueryWaitTaskRequest queryWaitTaskRequest) {
        int firstResult = queryWaitTaskRequest.getFirstResult();
        int maxResults = queryWaitTaskRequest.getMaxResults();
        if (maxResults == 0) {
            maxResults = 10;
        }
        List<TaskDTO> list = activitiService.queryWaitTask(firstResult, maxResults);
        return Result.ok().put("list", list);
    }


    /***
     * 查询用户任务列表
     * @return Result
     */

    @PostMapping(value = "/queryTask")
    @ApiOperation(value = "查询任务", notes = "查询任务")
    public Result queryTask(@RequestBody @ApiParam(value = "查询任务请求对象") @Valid QueryTaskRequest queryTaskRequest) {
        // 办理人
        String assignee = queryTaskRequest.getAssignee();
        // 候选人
        String candidateUser = queryTaskRequest.getCandidateUser();
        // 候选组
        String candidateGroup = queryTaskRequest.getCandidateGroup();
        // 第一个
        int firstResult = queryTaskRequest.getFirstResult();
        // 数量最大限制
        int maxResults = queryTaskRequest.getMaxResults();
        try {
            List<TaskDTO> list = activitiService
                    .queryTask(assignee, candidateUser, candidateGroup, firstResult, maxResults);
            return Result.ok().put("list", list);
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }

    /***
     * 撤回提交或审批
     * @param oldTaskId  历史任务id
     * @return 结果
     */
    @PostMapping(value = "/withdrawApproval")
    @ApiOperation(value = "撤回提交或审批", notes = "撤回提交或审批")
    public Result withdrawApproval(@RequestParam String oldTaskId) {
        activitiService.withdrawApproval(oldTaskId, "");
        return Result.ok();
    }

    /***
     * 审核任务
     * @param completeTaskRequest completeTaskReq对象
     * @return 结果
     */
    @PostMapping(value = "/completeTask")
    @ApiOperation(value = "审核任务", notes = "审核任务")
    public Result completeTask(@RequestBody @ApiParam(value = "审核任务请求对象") @Valid
                                       CompleteTaskRequest completeTaskRequest) {
        try {
            // 审核人不能为空
            String assignee = completeTaskRequest.getAssignee();
            if (StringUtils.isBlank(assignee)) {
                return Result.error(-1, "审核人不能为空");
            }
            // 流程是否完成
            Map<String, Object> param = new HashMap<>();
            param.put("isFinish", false);

            String taskId = completeTaskRequest.getTaskId();
            Map<String, Object> variables = completeTaskRequest.getVariables();
            if (completeTaskRequest.getIsReviewPass() == 1) {
                activitiService.completeTask(taskId, assignee, variables, param);
            }
            int returnStart = completeTaskRequest.getReturnStart();
            // 驳回
            if (completeTaskRequest.getIsReviewPass() == 0) {
                boolean restart = returnStart == 1;
                activitiService.rejectTask(taskId, assignee, variables, restart);
            }
            //流程是否结束
            return Result.ok().put("isFinish", param.get("isFinish"));
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }

    /****
     * 删除任务
     * @param deleteTaskRequest deleteTaskRequest
     * @return Result
     */
    @PostMapping(value = "/deleteTask")
    @ApiOperation(value = "删除任务", notes = "删除任务")
    public Result deleteTask(@RequestBody @ApiParam(value = "删除任务求对象")
                             @Valid DeleteTaskRequest deleteTaskRequest) {
        try {
            String taskId = deleteTaskRequest.getTaskId();
            activitiService.deleteTask(taskId);
            return Result.ok();
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }


    /****
     * 删除在途任务
     * @param deleteRuntimeTaskRequest 删除在途任务请求参数封装
     * @return Result
     */
    @PostMapping(value = "/deleteRuntimeTask")
    @ApiOperation(value = "删除在途任务", notes = "删除在途任务")
    public Result deleteRuntimeTask(@RequestBody @ApiParam(value = "删除任务求对象")
                                    @Valid DeleteRuntimeTaskRequest deleteRuntimeTaskRequest) {
        try {
            String deleteReason = deleteRuntimeTaskRequest.getDeleteReason();
            String processInstanceId = deleteRuntimeTaskRequest.getProcessInstanceId();
            activitiService.deleteRuntimeTask(processInstanceId, deleteReason);
            return Result.ok();
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }

    /***
     * 任务指派
     * @param claimTaskRequest claimTaskRequest
     * @return Result
     */
    @ApiOperation(value = "任务指派", notes = "任务指派")
    @PostMapping(value = "/claimTask")
    public Result claimTask(@RequestBody @ApiParam(value = "指派任务求对象") @Valid
                                    ClaimTaskRequest claimTaskRequest) {
        try {
            String taskId = claimTaskRequest.getTaskId();
            String assignee = claimTaskRequest.getAssignee();
            activitiService.claimTask(taskId, assignee);
            return Result.ok();
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }


    /****
     * 查询任务历史记录
     * @param queryTaskHistoryRequest queryTaskHistoryRequest
     * @return Result
     */
    @ApiOperation(value = "查询任务历史记录", notes = "查询任务历史记录")
    @PostMapping(value = "/queryTaskHistory")
    public Result queryTaskHistory(@RequestBody @ApiParam(value = "查询任务历史记录对象")
                                           QueryTaskHistoryRequest queryTaskHistoryRequest) {
        try {
            String processInstanceId = queryTaskHistoryRequest.getProcessInstanceId();
            List<HistoricTaskInstanceDTO> list = activitiService.queryTaskHistory(processInstanceId);
            return Result.ok().put("list", list);
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }

    /****
     * 查询任务历史记录
     * @param queryTaskHistoryRequest queryTaskHistoryRequest
     * @return Result
     */
    @ApiOperation(value = "查询任务历史变量记录", notes = "查询任务历史变量记录")
    @PostMapping(value = "/queryTaskHistoryVariables")
    public Result queryTaskHistoryVariables(@RequestBody @ApiParam(value = "查询任务历史记录对象")
                                                    QueryTaskHistoryRequest queryTaskHistoryRequest) {
        try {
            String processInstanceId = queryTaskHistoryRequest.getProcessInstanceId();
            List<HistoricVariableInstance> list = activitiService.queryTaskHistoryVariables(processInstanceId);
            return Result.ok().put("list", list);
        } catch (Exception e) {
            return Result.error(-1, e.getMessage());
        }
    }

    /**
     * 生成流程图
     *
     * @param response          httpServletResponse
     * @param processInstanceId 流程实例ID
     * @throws Exception v
     */
    @ApiOperation(value = "动态生成流程图")
    @GetMapping(value = "/processDiagram")
    public void genProcessDiagram(HttpServletResponse response, @RequestParam String processInstanceId) throws Exception {
        response.setContentType(MediaType.IMAGE_PNG_VALUE);
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] imgBytes = processImageService.getFlowImgByProcessInstanceId(processInstanceId);
        StreamUtils.copy(imgBytes, outputStream);
    }

}
